//go:build windows
// +build windows

/*
 *
 * Copyright (C) 2019 THL A29 Limited, a Tencent company.  All rights reserved.
 *
 *
 * A copy of the MIT License is included in this file.
 *
 *
 * Terms of the MIT License:
 * ---------------------------------------------------
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
 * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
 * the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
 * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

package main

import (
	"bufio"
	"errors"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
	"time"

	"gitee.com/daka1004/devops-runner/agentcommon/logs"

	"gitee.com/daka1004/devops-runner/agent/src/pkg/config"
	"gitee.com/daka1004/devops-runner/agent/src/pkg/constant"
	"gitee.com/daka1004/devops-runner/agent/src/pkg/util/systemutil"
	"gitee.com/daka1004/devops-runner/agentcommon/utils/fileutil"
	"github.com/kardianos/service"
)

const daemonProcess = "daemon"

func main() {
	isDebug := false
	if len(os.Args) == 2 {
		switch os.Args[1] {
		case "version":
			fmt.Println(config.AgentVersion)
			systemutil.ExitProcess(0)
		case "fullVersion":
			fmt.Println(config.AgentVersion)
			fmt.Println(config.GitCommit)
			fmt.Println(config.BuildTime)
			systemutil.ExitProcess(0)
		case "debug":
			isDebug = true
		}
	}

	// 初始化日志
	workDir := systemutil.GetExecutableDir()
	err := logs.Init(filepath.Join(workDir, "logs", "devopsDaemon.log"), isDebug, false)
	if err != nil {
		fmt.Printf("init daemon log error %v\n", err)
		systemutil.ExitProcess(1)
	}

	logs.Infof("GOOS=%s, GOARCH=%s", runtime.GOOS, runtime.GOARCH)

	err = os.Chdir(workDir)
	if err != nil {
		logs.Info("change work dir failed, err: ", err.Error())
		systemutil.ExitProcess(1)
	}

	defer func() {
		if err := recover(); err != nil {
			logs.Error("panic: ", err)
			systemutil.ExitProcess(1)
		}
	}()

	if ok := systemutil.CheckProcess(daemonProcess); !ok {
		logs.Info("get process lock failed, exit")
		return
	}

	logs.Info("devops daemon start")
	logs.Info("pid: ", os.Getpid())
	//logs.Info("pid: ", os.get())
	logs.Info("workDir: ", workDir)

	//服务定义
	serviceConfig := &service.Config{
		Name: "name",
	}

	daemonProgram := &program{}
	/*
		github.com/kardianos/service 是一个用于 Go 语言的跨平台服务管理库，
		主要用于将 Go 应用程序作为系统服务（Service/Daemon）运行
	*/
	sys := service.ChosenSystem()
	daemonService, err := sys.New(daemonProgram, serviceConfig)
	if err != nil {
		logs.WithError(err).Error("Init service error")
		systemutil.ExitProcess(1)
	}

	err = daemonService.Run()
	if err != nil {
		logs.WithError(err).Error("run agent program error")
	}
}

var GAgentProcess *os.Process = nil

/*
这段代码的逻辑是不断尝试启动 agent，不管之前是否已经启动。
如果 agent 已经在运行，新的实例会被启动，可能导致多个实例同时存在。这可能不符合预期，需要添加检查机制来避免重复启动
*/
// 从 agent.properties 读取配置参数
func readAgentProperties(workDir string) (map[string]string, error) {
	configPath := filepath.Join(workDir, ".agent.properties")
	file, err := os.Open(configPath)
	if err != nil {
		return nil, fmt.Errorf("读取配置文件失败: %v", err)
	}
	defer file.Close()

	properties := make(map[string]string)
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		line := strings.TrimSpace(scanner.Text())
		if line == "" || strings.HasPrefix(line, "#") { // 忽略空行和注释
			continue
		}
		// 按等号分割键值对
		keyValue := strings.SplitN(line, "=", 2)
		if len(keyValue) != 2 {
			continue
		}
		properties[strings.TrimSpace(keyValue[0])] = strings.TrimSpace(keyValue[1])
	}

	if err := scanner.Err(); err != nil {
		return nil, fmt.Errorf("扫描配置文件失败: %v", err)
	}
	return properties, nil
}

func watch() {
	workDir := systemutil.GetExecutableDir()
	agentPath := filepath.Join(systemutil.GetWorkDir(), "devops-runner.exe")

	// 读取配置文件
	props, err := readAgentProperties(workDir)
	if err != nil {
		logs.Fatalf("读取配置失败: %v", err)
	}

	// 检查必填参数（serverip 和 token）
	serverip, exists := props["serverip"]
	if !exists {
		logs.Fatal("配置文件中缺少 serverip 参数")
	}
	token, exists := props["token"]
	if !exists {
		logs.Fatal("配置文件中缺少 token 参数")
	}

	//可选参数（如 port，默认值示例）
	port := props["port"]
	if port == "" {
		port = "8080" // 设置默认值
	}

	for {
		func() {
			// 构建命令参数
			args := []string{
				"-serverip", serverip,
				"-token", token,
				"-serverport", port, // 可选参数
			}
			cmd := exec.Command(agentPath, args...)
			cmd.Dir = workDir

			logs.Info("启动 devops 代理")
			if !fileutil.Exists(agentPath) {
				logs.Errorf("代理文件：%s 不存在", agentPath)
				logs.Info("30 秒后重新启动")
				time.Sleep(30 * time.Second)
				return
			}

			// 后续逻辑（与原代码一致）
			err := fileutil.SetExecutable(agentPath)
			if err != nil {
				logs.WithError(err).Error("chmod 失败")
				logs.Info("30 秒后重新启动")
				time.Sleep(30 * time.Second)
				return
			}
			logs.Info("启动命令：", cmd.Args)
			if err := cmd.Start(); err != nil {
				logs.WithError(err).Error("代理启动失败")
				logs.Info("30 秒后重新启动")
				time.Sleep(30 * time.Second)
				return
			}

			GAgentProcess = cmd.Process
			logs.Info("devops 代理已启动，pid：", cmd.Process.Pid)
			if err := cmd.Wait(); err != nil {
				// 错误处理逻辑不变
				var exitErr *exec.ExitError
				if errors.As(err, &exitErr) {
					if exitErr.ExitCode() == constant.DaemonExitCode {
						logs.Warnf("退出代码 %d，正常退出", constant.DaemonExitCode)
						systemutil.ExitProcess(constant.DaemonExitCode)
					}
				}
				logs.WithError(err).Error("代理进程错误")
			}
			logs.Info("代理进程已退出，30 秒后重启")
			time.Sleep(30 * time.Second)
		}()
	}
}

//func watch() {
//	workDir := systemutil.GetExecutableDir()
//	var agentPath = systemutil.GetWorkDir() + "/devops-runner.exe"
//	for {
//		func() {
//			cmd := exec.Command(agentPath, "-serverip", "127.0.0.1")
//			cmd.Dir = workDir
//
//			logs.Info("start devops agent")
//			if !fileutil.Exists(agentPath) {
//				logs.Errorf("agent file: %s not exists", agentPath)
//				logs.Info("restart after 30 seconds")
//				time.Sleep(30 * time.Second)
//			}
//
//			err := fileutil.SetExecutable(agentPath)
//			if err != nil {
//				logs.WithError(err).Error("chmod failed, err")
//				logs.Info("restart after 30 seconds")
//				time.Sleep(30 * time.Second)
//				return
//			}
//
//			err = cmd.Start()
//			if err != nil {
//				logs.WithError(err).Error("agent start failed, err")
//				logs.Info("restart after 30 seconds")
//				time.Sleep(30 * time.Second)
//				return
//			}
//
//			GAgentProcess = cmd.Process
//			logs.Info("devops agent started, pid: ", cmd.Process.Pid)
//			err = cmd.Wait()
//			if err != nil {
//				var exitErr *exec.ExitError
//				if errors.As(err, &exitErr) {
//					if exitErr.ExitCode() == constant.DaemonExitCode {
//						logs.Warnf("exit code %d daemon exit", constant.DaemonExitCode)
//						systemutil.ExitProcess(constant.DaemonExitCode)
//					}
//				}
//				logs.WithError(err).Error("agent process error")
//			}
//			logs.Info("agent process exited")
//
//			logs.Info("restart after 30 seconds")
//			time.Sleep(30 * time.Second)
//		}()
//	}
//}

type program struct {
}

func (p *program) Start(s service.Service) error {
	go watch()
	return nil
}

func (p *program) Stop(s service.Service) error {
	p.tryStopAgent()
	return nil
}

func (p *program) tryStopAgent() {
	if GAgentProcess != nil {
		GAgentProcess.Kill()
	}
}
